/**   
 * Copyright 2011 COMERE Harold
 * 
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 * 
 *   http://www.apache.org/licenses/LICENSE-2.0
 * 
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */
package etrl.geometry;

import java.util.ArrayList;
import java.util.Iterator;

import etrl.core.BoundingBox;
import etrl.vecmath.Vector3f;

/**
 * \class VertexArray
 * \brief Class representing an array of Vertex to describe a geometry.
 * @author harold
 *
 */
public class VertexArray 
{
	/**
	 * Container to store vertice
	 */
	private ArrayList <Vertex> _vertice;
	
	/**
	 * AABB containing the drawable
	 */
	private BoundingBox _boundingBox;
	
	/**
	 * Minimum coords from all vertice, used to compute bounding sphere
	 */
	private Vector3f _min;
	
	/**
	 * Maximum coords fromm all vertice, used to compute bounding sphere
	 */
	private Vector3f _max;
	
	/**
	 * \brief Initialize an empty vertex array
	 */
	public VertexArray()
	{
		_vertice = new ArrayList <Vertex>();
		_boundingBox = new BoundingBox();
	}
	
	/**
	 * \brief Registers a new vertex 
	 * @param[in] vertex The vertex to add.
	 */
	public void push_back(Vertex vertex)
	{
		// If there is no any vertex registered yet, use this vertex coord to 
		// initialize the min and max coords
		if(_vertice.size() == 0)
		{
			_min = new Vector3f(vertex._coordinate.x, vertex._coordinate.y, vertex._coordinate.z);
			_max = new Vector3f(vertex._coordinate.x, vertex._coordinate.y, vertex._coordinate.z);
			
			// And the bounding sphere center becomes this vertex and still have a radius = 0...
			_boundingBox.setMin(_min);
			_boundingBox.setMax(_max);
		}
		else 
		{
			// else there is already some vertice so the min and max are initialized,
			// make comparaison with given vertex to update bounding sphere if needed
			if(vertex._coordinate.x < _min.x) _min.x = vertex._coordinate.x;
			if(vertex._coordinate.y < _min.y) _min.y = vertex._coordinate.y;
			if(vertex._coordinate.z < _min.z) _min.z = vertex._coordinate.z;
			
			if(vertex._coordinate.x > _max.x) _max.x = vertex._coordinate.x;
			if(vertex._coordinate.y > _max.y) _max.y = vertex._coordinate.y;
			if(vertex._coordinate.z > _max.z) _max.z = vertex._coordinate.z;
			
			_boundingBox.setMin(_min);
			_boundingBox.setMax(_max);
		}
		
		_vertice.add(vertex);
	}
	
	/**
	 * \brief Clears the vertex array.
	 */
	public void clear()
	{
		_vertice.clear();
	}
	
	/**
	 * \brief Gets the vertex array as float array ready to be sent to webgl
	 * @return Vertex array as float[]
	 */
	public float[] toFloatArray()
	{
		float[] array = new float[13 * _vertice.size()];
		
		int index = 0;
		for(Iterator <Vertex> it = _vertice.iterator(); it.hasNext();)
		{
			Vertex vertex = it.next();
			array[13 * index] = vertex._coordinate.x;
			array[13 * index + 1] = vertex._coordinate.y;
			array[13 * index + 2] = vertex._coordinate.z;
			array[13 * index + 3] = vertex._coordinate.w;
			array[13 * index + 4] = vertex._color.x;
			array[13 * index + 5] = vertex._color.y;
			array[13 * index + 6] = vertex._color.z;
			array[13 * index + 7] = vertex._color.w;
			array[13 * index + 8] = vertex._normal.x;
			array[13 * index + 9] = vertex._normal.y;
			array[13 * index + 10] = vertex._normal.z;
			array[13 * index + 11] = vertex._texCoord.x;
			array[13 * index + 12] = vertex._texCoord.y;
			
			++index;
		}
		
		return array;
	}
	
	/**
	 * \brief Gets the number of vertice in the array.
	 * @return Vertex count.
	 */
	public int size()
	{
		return _vertice.size();
	}
	
	/**
	 * \brief Gets the bounding box containing all the vertice.
	 * @return Vertice bounding box
	 */
	public BoundingBox getBoundingBox()
	{
		return _boundingBox.clone();
	}
	
	/**
	 * \brief Gets the list of vertice.
	 * @return Vertice list.
	 */
	public ArrayList <Vertex> getVertice()
	{
		return _vertice;
	}
}
